package com.hw.common.redis;

import com.hw.common.utils.ObjectUtils;
import com.hw.common.utils.SpringContextHolder;
import com.hw.common.utils.StringUtils;
import redis.clients.jedis.JedisCluster;

import java.util.HashMap;
import java.util.Map;


@SuppressWarnings({"rawtypes","unchecked"})
public class DisHashCache<K, V> implements Cache<K, V> {
	public static final String USERS_HASH_CACHE = "user_cache";
	public static final String USERS_EXAM_REPORT = "user_exam_report";
	public static final String USERS_REAL_NAME = "user_real_name";
	private static final String cacheKeyPrefix = "hash_";
	
//	private static Map<String, DisHashCache> caches = new HashMap<String, DisHashCache>();
	private static Map<String, Integer> modNumByKeyMap = new HashMap<String, Integer>();
	
	static{
		modNumByKeyMap.put(USERS_HASH_CACHE, 1024);
		modNumByKeyMap.put(USERS_EXAM_REPORT, 1024);
		modNumByKeyMap.put(USERS_REAL_NAME, 1024);
	}
	
	private String cacheKeyName;
	private int modNum = 0;
	private JedisCluster jedisCluster = null;
	
	public static DisHashCache newInstance(String name){
		return new DisHashCache(name);
	}
	
	public static DisHashCache newInstance(String name,JedisCluster jedisCluster){
		return new DisHashCache(name,jedisCluster);
	}
	
	private DisHashCache(String name){
		cacheKeyName = cacheKeyPrefix + name;
		if(null!=modNumByKeyMap.get(name)){
			modNum = modNumByKeyMap.get(name);
		}
		try{
			jedisCluster = SpringContextHolder.getBean("jedisCluster");
		}catch(Exception e){
		}
	}
	
	private DisHashCache(String name,JedisCluster jedisCluster){
		cacheKeyName = cacheKeyPrefix + name;
		if(null!=modNumByKeyMap.get(name)){
			modNum = modNumByKeyMap.get(name);
		}
		this.jedisCluster = jedisCluster;
	}

	@Override
	public V get(K field) {
		String key = getKeyByField(field);
		V value = (V)toObject(jedisCluster.hget(getBytesKey(key),getBytesKey(field)));
		return value;
	}

	@Override
	public V put(K field, V value)  {
		String key = getKeyByField(field);
		jedisCluster.hset(getBytesKey(key),getBytesKey(field),toBytes(value));
		return value;
	}

	@Override
	public Long remove(K field) {
		String key = getKeyByField(field);
		return jedisCluster.hdel(getBytesKey(key),getBytesKey(field));
	}
	
	@Override
	public int size(K key) {
		return -1;
	}

	@Override
	public void clear() {
	}
	
	/**
	 * Object转换byte[]类型
	 * @param key
	 * @return
	 */
	private byte[] toBytes(Object object){
    	return ObjectUtils.serialize(object);
	}
	
	private Object toObject(byte[] bytes){
		return ObjectUtils.unserialize(bytes);
	}
	
	private byte[] getBytesKey(Object object){
		if(object instanceof String){
    		return StringUtils.getBytes((String)object);
    	}else{
    		return ObjectUtils.serialize(object);
    	}
	}
	
	private String getKeyByField(Object field){
		return 0==modNum?cacheKeyName:cacheKeyName + '_' +(field.hashCode() & 0x7FFFFFFF % modNum);
	}
	
	public static void main(String[] args) {
		System.out.println("hash_user_cache_"+("ln4_15270905090".hashCode() & 0x7FFFFFFF % 1024));
		System.out.println("hash_user_cache_"+("tariff_exam_18770813252".hashCode() & 0x7FFFFFFF % 1024));
	}
}
